package com.yunxi.poc.starbucks.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunxi.poc.starbucks.entity.Tb1StoreData;
import com.yunxi.poc.starbucks.mapper.Tb1StoreDataMapper;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;

@SpringBootTest
@RunWith(SpringRunner.class)
class ImportStoreLocation {

    private final static Logger logger = LoggerFactory.getLogger(ImportStoreLocation.class);

    @Resource
    Tb1StoreDataMapper tb1StoreDataMapper;

    @Test
    void importLocation() {
        List<String> ids = this.tb1StoreDataMapper.allStoreIds(new QueryWrapper<>());
//        List<String> ids = Arrays.asList("16519");

        RestTemplate restTemplate = new RestTemplate();

        MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        header.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

        /**
         * delete index
         */
        HttpEntity<MultiValueMap> deleteIndexReq = new HttpEntity(new JSONObject(), header);
        ResponseEntity<JSONObject> deleteIndexRes = restTemplate.exchange(
                "http://10.92.208.3:9200/store_geo_shape",
                HttpMethod.DELETE, deleteIndexReq, JSONObject.class);

        /**
         * new mapping
         */
        String mappingStr = "{\n" +
                "  \"mappings\": {\n" +
                "    \"_doc\": {\n" +
                "      \"properties\": {\n" +
                "        \"store_id\": { \"type\": \"keyword\" },\n" +
                "        \"location\": { \"type\": \"geo_shape\"  }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";
        JSONObject mapping = JSONUtil.parseObj(mappingStr);
        HttpEntity<MultiValueMap> mappingReq = new HttpEntity(mapping, header);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ResponseEntity<JSONObject> mappingRes = restTemplate.exchange(
                "http://10.92.208.3:9200/store_geo_shape?pretty",
                HttpMethod.PUT, mappingReq, JSONObject.class);

        /**
         * inset doc
         */
        for (String storeId : ids) {
            QueryWrapper<Tb1StoreData> queryCond = new QueryWrapper<>();
            queryCond.select("latitude", "longitude");
            queryCond.eq("store_id", storeId);
            List<Tb1StoreData> stores = this.tb1StoreDataMapper.selectList(queryCond);
            List<double[]> coordinates_1 = new ArrayList<>();
            for (Tb1StoreData store : stores) {
                double[] locs = {Double.parseDouble(store.getLongitude()), Double.parseDouble(store.getLatitude())};
                coordinates_1.add(locs);
            }

            JSONObject doc = new JSONObject().set("store_id", storeId);
            Map location = new HashMap();
            location.put("type", "polygon");
            List<List<double[]>> coordinates = new ArrayList<>();
            coordinates.add(coordinates_1);
            location.put("coordinates", coordinates);
            doc.set("location", location);
            // System.out.println(doc.toStringPretty());

            HttpEntity<MultiValueMap> docReq = new HttpEntity(doc, header);
            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            try {
                ResponseEntity<JSONObject> insertDocRes = restTemplate.exchange(
                        "http://10.92.208.3:9200/store_geo_shape/_doc",
                        HttpMethod.POST, docReq, JSONObject.class);
            } catch (Exception e) {
                logger.error("============storeId============" + storeId + doc.toStringPretty());
            }
        }

        Assert.assertNotNull(1);
    }

    @Test
    void searchGeoShape() {
        MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        header.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

        String queryStr = "{\n" +
                "  \"query\": {\n" +
                "    \"bool\": {\n" +
                "      \"must\": {\n" +
                "        \"match_all\": {}\n" +
                "      },\n" +
                "      \"filter\": {\n" +
                "        \"geo_shape\": {\n" +
                "          \"location\": {\n" +
                "            \"shape\": {\n" +
                "              \"type\": \"point\",\n" +
                "              \"coordinates\": [114.086697,22.554429]\n" +
                "            },\n" +
                "            \"relation\": \"intersects\"\n" +
                "          }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";
        JSONObject mapping = JSONUtil.parseObj(queryStr);
        HttpEntity<MultiValueMap> mappingReq = new HttpEntity(mapping, header);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ResponseEntity<JSONObject> mappingRes = restTemplate.exchange(
                "http://10.92.208.3:9200/store_geo_shape/_search?pretty&filter_path=hits.hits._source.store_id",
                HttpMethod.GET,
                mappingReq,
                JSONObject.class);

        logger.error(Objects.requireNonNull(mappingRes.getBody()).toStringPretty());
        Assert.assertNotNull(mappingRes.getBody().toStringPretty());
    }
}